import { JoinClient } from 'meteor-publish-join';

/**
 * enable infiniteScroll on a Template
 * @param {object} options 
 */
Blaze.TemplateInstance.prototype.infiniteScroll = function (options) {
  let defaults = {
    // 查询条件
    query: {},
    // 每次请求的条数
    perPage: 10,
    // 发布源名称
    publication: null,
    // 计算总数名称
    countPublication: null,
    // 目标容器元素
    element: null,
    // 距离底部的偏移量
    threshold: 100,
    // 是否使用window滚动条
    useWindow: true,
    // 向上滚动至顶部时是否加载数据,为[true]向下不可用
    topLoad: false,
    // 当前模板是否被渲染
    templateRendered: false
  };

  this.infiniteScroll.options = options = _.extend({}, defaults, options);

  let self = this;

  let container = $(window);
  this.autorun(() => {
    if (options.templateRendered) {
      if (!options.useWindow && options.element) {
        container = $(options.element);
      }
    }
  });

  let total;

  let limit = new ReactiveVar();
  
  this.autorun(() => {
    limit.set(options.perPage);
  });

  this.autorun(() => {
    let lmt = limit.get();
    
    this.resultSub = this.subscribe(options.publication, options.query, lmt);
  });

  this.autorun(() => {
    if (Counts.has(options.countPublication)) {
      total = Counts.get(options.countPublication);
    } else {
      total = JoinClient.get(options.countPublication);
    }
  });

  // 计算是否到了顶部
  const calculateTopPosition = (callback) => {
    let scrollTop = container.scrollTop();
    if (scrollTop <= options.threshold) {
      container.off('scroll');
      setTimeout(() => {
        callback();
      }, 500);
    }
  };

  // 计算是否到了底部
  const calculateBottomPosition = (callback) => {
    let scrollTop = container.scrollTop();
    let windowHeight = container.height();
    let scrollHeight = $(document).height();

    this.autorun(() => {
      if (options.templateRendered) {
        if (!options.useWindow) {
          scrollHeight = $('#infinite-scroll-container').height();
        }
      }
    });
    
    if (scrollTop + windowHeight >= scrollHeight - options.threshold) {
      container.off('scroll');
      setTimeout(() => {
        callback();
      }, 500);
    }
  };

  const loadMore = () => {
    let lmt = limit.get();
    
    if (total > lmt) {
      limit.set(lmt + options.perPage);
    }
  };

  this.autorun(() => {
    if (this.resultSub.ready()) {
      container.on('scroll', () => {
        if (options.topLoad) {
          calculateTopPosition(loadMore);
        } else {
          calculateBottomPosition(loadMore);
        }
      });
    }
  });

  this.getLimit = function () {
    return limit.get();
  };
};

Template.infinite_scroll.onDestroyed(function() {
  let view = this.view;

  if (view.parentView) {
    view = view.parentView;
  } else {
    return;
  }

  let tpl = view.templateInstance();

  if (tpl.infiniteScroll.options.element) {
    $(tpl.infiniteScroll.options.element).off('scroll');
  } else {
    $(window).off('scroll');
  }
});

Template.infinite_scroll.helpers({
  loading: () => {
    let view = Template.instance().view;

    if (view.parentView) {
      view = view.parentView;
    } else {
      return;
    }

    let tpl = view.templateInstance();

    if (!tpl.resultSub) {
      return;
    }

    return !tpl.resultSub.ready();
  }
});
